package org.crumbleworks.crumbcrane.entity;

/**
 * The Class Entity.
 */
public abstract class Entity2D {
    private final int LOCATION_ARRAY_LENGTH = 2;
    private final int SIZE_ARRAY_LENGTH = 2;
    private final int COLOR_ARRAY_LENGTH = 3;
    
    private double x, y, width, height, r, g, b;
    
    /**
     * Instantiates a new entity.
     * 
     * @param x the x
     * @param y the y
     * @param width the width
     * @param height the height
     * @param r the r
     * @param g the g
     * @param b the b
     */
    public Entity2D(double x, double y, double width, double height, double r, double g, double b) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.r = r;
        this.g = g;
        this.b = b;
    }

    // TODO do something with POINT

    /**
     * Gets the location.
     * 
     * @return the location
     */
    public double[] getLocation() {
        double[] location = { x, y };
        return location;
    }

    /**
     * Sets the location.
     * 
     * @param x the x
     * @param y the y
     */
    public void setLocation(double x, double y) {
        this.x = x;
        this.y = y;
    }

    /**
     * Returns false if location.length is less than LOCATION_ARRAY_LENGTH,<br />
     * else sets variables x and y and returns true.<br /><br />
     * 
     * x&nbsp;= location[0]<br />
     * y&nbsp;= location[1]
     * 
     * @param location the new location
     * @return false if location.length is less than LOCATION_ARRAY_LENGTH, else true
     */
    public boolean setLocation(double[] location) {
        if(location.length < LOCATION_ARRAY_LENGTH)
            return false;
        
        this.x = location[0];
        this.y = location[1];
        
        return true;
    }

    /**
     * Gets the size.
     * 
     * @return the size
     */
    public double[] getSize() {
        double[] size = { width, height };
        return size;
    }

    /**
     * Sets the size.
     * 
     * @param width the width
     * @param height the height
     */
    public void setSize(double width, double height) {
        this.width = width;
        this.height = height;
    }

    /**
     * Returns false if size.length is less than SIZE_ARRAY_LENGTH,<br />
     * else sets variables width and height and returns true.<br /><br />
     * 
     * width&nbsp;&nbsp;= size[0]<br />
     * height&nbsp;= size[1]
     * 
     * @param size the new size
     * @return false if size.length is less than SIZE_ARRAY_LENGTH, else true
     */
    public boolean setSize(double[] size) {
        if(size.length < SIZE_ARRAY_LENGTH)
            return false;
        
        this.width = size[0];
        this.height = size[1];
        
        return true;
    }

    // TODO add color methods for COLOR

    /**
     * Gets the color.
     * 
     * @return the color
     */
    public double[] getColor() {
        double[] color = { r, g, b };
        return color;
    }

    /**
     * Sets the color.
     * 
     * @param r the r
     * @param g the g
     * @param b the b
     */
    public void setColor(double r, double g, double b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    /**
     * Returns false if color.length is less than COLOR_ARRAY_LENGTH,<br />
     * else sets variables r, g and b and returns true.<br /><br />
     * 
     * r&nbsp;&nbsp;= color[0]<br />
     * g&nbsp;= color[1]<br />
     * b&nbsp;= color[2]
     * 
     * @param color the new color
     * @return false if color.length is less than COLOR_ARRAY_LENGTH, else true
     */
    public boolean setColor(double[] color) {
        if(color.length < COLOR_ARRAY_LENGTH)
            return false;
        
        this.r = color[0];
        this.g = color[1];
        this.b = color[2];
        
        return true;
    }

    /**
     * Returns true if the given Point (calculated out of x, y) is inside this
     * Entity, else false.
     * 
     * @param x the x coordinate
     * @param y the y coordinate
     */
    public boolean inBounds(double x, double y) {
        boolean xOK = false;
        boolean yOK = false;

        if((x > this.x) && (x < (this.x + this.width))) {
            xOK = true;
        }
        if((y > this.y) && (y < (this.y + this.height))) {
            yOK = true;
        }

        if(xOK && yOK) {
            return true;
        }
        return false;

        // return (xOK && yOK) ? true : false;
    }

    /**
     * The x coordinate is location[0]. The y coordinate is location[1].
     * 
     * Invokes inBounds(int x, int y) and returns its return value.
     * 
     * @param location a double array with the x and y coordinate
     */
    public boolean inBounds(double[] location) {
        return inBounds(location[0], location[1]);
    }

    /**
     * The x coordinate is entity.getX(). The y coordinate is entity.getY().
     * 
     * Invokes inBounds(int x, int y) and returns its return value.
     * 
     * @param entity an other entity than this
     */
    public boolean inBounds(Entity2D entity) {
        return inBounds(entity.getX(), entity.getY());
    }

    // TODO implement this feature
    public boolean intersects(Entity2D entity) {
        return false;
    }

    /**
     * Gets the x.
     * 
     * @return the x
     */
    public double getX() {
        return x;
    }

    /**
     * Sets the x.
     * 
     * @param x the x to set
     */
    public void setX(double x) {
        this.x = x;
    }

    /**
     * Gets the y.
     * 
     * @return the y
     */
    public double getY() {
        return y;
    }

    /**
     * Sets the y.
     * 
     * @param y the y to set
     */
    public void setY(double y) {
        this.y = y;
    }

    /**
     * Gets the width.
     * 
     * @return the width
     */
    public double getWidth() {
        return width;
    }

    /**
     * Sets the width.
     * 
     * @param width the width to set
     */
    public void setWidth(double width) {
        this.width = width;
    }

    /**
     * Gets the height.
     * 
     * @return the height
     */
    public double getHeight() {
        return height;
    }

    /**
     * Sets the height.
     * 
     * @param height the height to set
     */
    public void setHeight(double height) {
        this.height = height;
    }

    /**
     * Gets the r.
     * 
     * @return the r
     */
    public double getR() {
        return r;
    }

    /**
     * Sets the r.
     * 
     * @param r the r to set
     */
    public void setR(double r) {
        this.r = r;
    }

    /**
     * Gets the g.
     * 
     * @return the g
     */
    public double getG() {
        return g;
    }

    /**
     * Sets the g.
     * 
     * @param g the g to set
     */
    public void setG(double g) {
        this.g = g;
    }

    /**
     * Gets the b.
     * 
     * @return the b
     */
    public double getB() {
        return b;
    }

    /**
     * Sets the b.
     * 
     * @param b the b to set
     */
    public void setB(double b) {
        this.b = b;
    }

    public abstract void draw();
}
